#include "mb_sto_dev.h"

/* sto 设备私有数据 */
sto_prvt s_sto_prvt = 
{
    /* 历史选择记录全部初始化为 STO_UNKNOWN */
    .sel_history = STO_DEV_SELS_INIT_CFG,
};

/* sto 设备操作对象结构体 */
sto_op_t s_sto_ops[STO_SELECT_MAX_NBR];

#ifndef MB_DEV_DISABLE_INIT
/* sto 设备初始化函数 (新的设备初始化函数, 添加到此处) */
sto_init sto_inits[STO_SELECT_MAX_NBR] =
{
    /* STO_ROM */
    NULL,
    /* STO_SPIFLASH */
    NULL,
    /* STO_QSPIFLASH */
    NULL,
    /* STO_SDCARD */
    NULL
};
#endif

/* sto 设备注册函数接口 (新的设备操作注册函数, 添加到此处)  */
sto_op_register sto_op_register_funcs[STO_SELECT_MAX_NBR] = 
{
    /* STO_ROM */
    sto_rom_op_register,

    /* STO_SPIFLASH */
    sto_spiflash_op_register,

    /* STO_QSPIFLASH */
    sto_qspiflash_op_register,

    /* STO_SDCARD */
    NULL
};

/* -------------------------- sto 设备初始化 -------------------------- */

/* 选择 sto 设备 */
static int mb_sto_dev_select(STO_SELECT sel)
{
    int i;

    /* 判断是否已经选择过设备 */
    for (i = 0; i < sizeof(s_sto_prvt.sel_history); i++)
    {
        
        if (s_sto_prvt.sel_history[i] == sel)
        {
            return -1;  /* sel 在 当前系统中 已被选择(处于可用状态) */
        }
    }

    /* 是新的设备选择 */
    s_sto_prvt.cursel =  sel;

    return 0;
}

/* 注册 sto 硬件设备操作 */
static sto_op_t mb_sto_dev_op_register(void)
{
    /* 判断当前设备是否已被注册 */
    if (s_sto_prvt.sel_history[s_sto_prvt.cursel] != STO_UNKNOWN)
    {
        return NULL;
    }

    /* 注册设备操作接口 */
    s_sto_ops[s_sto_prvt.cursel] = sto_op_register_funcs[s_sto_prvt.cursel]();

    /* 将该设备加进设备选择记录 */
    s_sto_prvt.sel_history[s_sto_prvt.cursel] = s_sto_prvt.cursel;

    /* 返回这个设备的操作接口 */
    return s_sto_ops[s_sto_prvt.cursel];
}

/* ----------------------------- 注册指定的STO设备操作函数接口 ----------------------------- */

/* 注册 sto 设备操作 */
sto_op_t mb_sto_op_register(STO_SELECT sel)
{
    int      ret;
    sto_op_t sret;

    /* 判断参数有效性 */
    if (sel >= STO_UNKNOWN)
    {
        return NULL;    /* 注册失败 */
    }

    /* 选择 sto 设备 */
    ret = mb_sto_dev_select(sel);

    if (ret != 0)
    {
        return NULL;    /* 硬件设备选择失败, 已被选择(处于可用状态) */
    }

    /* 注册 sto 硬件设备操作 */
    sret = mb_sto_dev_op_register();

    if (sret == NULL)
    {
        return NULL;    /* 设备未被选择, 但是硬件操作函数注册失败 */
    }

    /* 返回该 STO 设备操作函数接口 */
    return sret;
}
